/************** Guangxi *****************/
#pragma once

#include "Grids.h"
#include "contest_coord.h"
#include "contest_pin.h"
#include <unordered_set>
#include "contest_net.h"
#include "./Third/CoordEncoding/CoordinateCodec.hpp"

namespace ieda_contest {

class ContestDataManager;
class Route;

class RoutingBoundaryInfo {
public:
    // RoutingBoundaryInfo() = default;
    RoutingBoundaryInfo(ContestCoord first_coordinate,
                        ContestCoord second_coordinate,
                        cell_move_router::CoordinateCodec<unsigned long long> &&Codec,
                        std::unordered_set<size_t> &&Terminals,
                        std::vector<ContestSegment> &&RouteUnderMinLayer);
    ~RoutingBoundaryInfo() = default;

    ContestCoord& getStartCoordinate() {return _first_coordinate; }
    ContestCoord& getEndCoordinate() {return _second_coordinate; }
    const std::unordered_set<size_t> &get_terminals() const {return _Terminals; }
    const std::vector<ContestSegment> &routeUnderMinLaye() const {return _RouteUnderMinLayer; }
    std::vector<ContestSegment> &&routeUnderMinLayeV2()  {return std::move(_RouteUnderMinLayer); }
    cell_move_router::CoordinateCodec<unsigned long long>& get_CodeC() {return _Codec; }
    //void setStartCoordinate(ContestCoord first_coordinate) {_first_coordinate = first_coordinate; }
    //void setEndCoordinate(ContestCoord second_coordinate) {_second_coordinate = second_coordinate; }


private:
    ContestCoord _first_coordinate;
    ContestCoord _second_coordinate;
    cell_move_router::CoordinateCodec<unsigned long long> _Codec;
    std::unordered_set<size_t> _Terminals;
    std::vector<ContestSegment> _RouteUnderMinLayer;
    
};

class BoundaryBuilder {
// 针对单一的Net
public:
    BoundaryBuilder(ContestDataManager* data_manager,
                    ContestNet *SingeNetPtr,
                    std::vector<ContestSegment> &OriginRoute);
    ~BoundaryBuilder() = default;
    bool isBoundaryInfoExist() const { return _BoundaryInfoExist; }
    bool checkPins() const; 
    bool checkRoute(ContestSegment &RouteSegement) const;
    void createBoundaryInfo();
    void setBoundaryInfoExist(bool flag) {_BoundaryInfoExist = flag; }
    ContestNet* getSingleNetPtr() const {return _SingeNetPtr; }
    ContestCoord& getStartCoordinate() {return _start_coordinate; }
    ContestCoord& getEndCoordinate() {return _end_coordinate; }
    void setStartCoordinate(ContestCoord start_coordinate) {_start_coordinate = start_coordinate; }
    void setEndCoordinate(ContestCoord end_coordinate) {_end_coordinate = end_coordinate; }
    std::unordered_set<size_t>& get_termial() {return _Terminals; }
    void set_termial(size_t inputTermial) {_Terminals.emplace(inputTermial); }
    void clear_terminal() {_Terminals.clear(); }
    std::vector<ContestSegment>& get_routeUnderMinLayer() {return _RouteUnderMinLayer; }
    void clear_routeUnderMinLayer() {_RouteUnderMinLayer.clear(); }
    void set_routeUnderMinLayer(const ContestCoord& p1, const ContestCoord& p2) {_RouteUnderMinLayer.emplace_back(p1, p2); }
    RoutingBoundaryInfo getBoundaryInfo();
    cell_move_router::CoordinateCodec<unsigned long long>& get_CodeC() {return _Codec; }
    void set_CodeC(int x, int y, int L);



private:
    ContestDataManager* _data_manager;
    ContestNet *_SingeNetPtr;
    std::vector<ContestSegment> &_OriginRoute;
    std::vector<ContestSegment> _RouteUnderMinLayer;
    bool _BoundaryInfoExist;
    std::unordered_set<size_t> _Terminals;
    ContestCoord _start_coordinate;
    ContestCoord _end_coordinate;
    cell_move_router::CoordinateCodec<unsigned long long> _Codec;
};




} // ieda_contest